package com.sky.service.rider.impl;

import com.sky.dto.UserLoginDTO;
import com.sky.exception.CodeErrorException;
import com.sky.exception.CodeExpiredException;
import com.sky.exception.NoCourierException;
import com.sky.exception.ParameterIsNullException;
import com.sky.mapper.common.ShortUrlMapper;
import com.sky.mapper.courier.CourierMapper;
import com.sky.mapper.courier.CourierTradeOrderMapper;
import com.sky.mapper.user.OrderMapper;
import com.sky.pojo.Courier;
import com.sky.pojo.CourierTradeOrder;
import com.sky.pojo.Orders;
import com.sky.pojo.ShortUrl;
import com.sky.result.Result;
import com.sky.service.rider.CourierService;
import com.sky.shoturi.ShortUrlGenerator;
import com.sky.vo.CourierTradeOrderDetailItemVO;
import com.sky.vo.CourierTradeOrderDetailVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

@Service
public class CourierServiceImpl implements CourierService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CourierMapper courierMapper;

    @Autowired
    private CourierTradeOrderMapper courierTradeOrderMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ShortUrlGenerator shortUrlGenerator;

    @Autowired
    private ShortUrlMapper shortUrlMapper;
    @Override
    public Result<Courier> login(UserLoginDTO dto) {

        //验参
        if(dto==null){
            throw new ParameterIsNullException("参数为null");
        }

        //1.比较验证码
        String code = (String) redisTemplate.opsForValue().get("code:" + dto.getTelephone());
        if(StringUtils.isEmpty(code)){
            throw new CodeExpiredException("验证码过期，请重新发送");
        }
        if(!code.equals(dto.getCode())){
            throw new CodeErrorException("验证码错误");
        }
        //2.获取骑手信息

        // 模拟器不获取位置，实际前端登录提交骑手位置，我们更新入库
        Courier courier = courierMapper.selectByPhone(dto.getTelephone());
        if(courier==null){
            throw new NoCourierException("请先注册为骑手");
        }

        return Result.success(courier);
    }

    @Override
    @Transactional
    public Result<String> receivingOrder(Long courierId, Long tradeNo) {

        //验参
        if(courierId==null||tradeNo==null){
            throw new ParameterIsNullException("参数为null");
        }

        //修改运单的状态
        courierTradeOrderMapper.updateStatusByTradeNo(tradeNo, CourierTradeOrder.DELIVORING);
        //修改订单的状态
        CourierTradeOrder courierTradeOrder = courierTradeOrderMapper.selectByTradeNo(tradeNo);
        orderMapper.updateOrderStatusByNumber(courierTradeOrder.getOrderNumber(), Orders.TOBEPICKEDUP);

        //发送短信通知用户
        sendMesssageToCustomer(courierTradeOrder);

        return Result.success();
    }

    private void sendMesssageToCustomer(CourierTradeOrder tradeOrder) {
        //String url = "https://k3663s4033.zicp.fun/rider.html?tradeNo="+tradeOrder.getTradeNo()+"&courierId="+tradeOrder.getCourierId()+"&expire=2023-09-27 16:09:00";
        //1.生成短编码  ，bitmap判重
        String code = "";
        while (true){
            long index = 0l;
            code = shortUrlGenerator.creatKey();
            int hashCode = code.hashCode();
            if(hashCode<0){
                index = Math.abs(hashCode)+2147483648l;
            }else{
                index = hashCode;
            }
            //判断bit位是否存在
            Boolean res = redisTemplate.opsForValue().getBit("short_code", index);
            if(!res){
                //生成成功，将bit位置为存在
                redisTemplate.opsForValue().setBit("short_code",index,true);
                break;
            }
        }

        //2.拼接短链
        String shortUrl = shortUrlGenerator.getShortUrl(code);

        //2.生成fullUrl
        String fullUrl = shortUrlGenerator.getFullUrl(tradeOrder.getTradeNo(),
                tradeOrder.getCourierId(),
                tradeOrder.getCustomerExpectedDeliveryTime());

        //3.保存入库发送短信
        ShortUrl shortUrlPojo = ShortUrl.builder()
                                .shortUrl(shortUrl)
                                .fullUrl(fullUrl)
                                .expireTime(tradeOrder.getCustomerExpectedDeliveryTime())
                                .shortCode(code)
                                .tradeNo(tradeOrder.getTradeNo())
                                .build();
        shortUrlMapper.save(shortUrlPojo);

        System.out.println("--------发送短信通知用户:"+shortUrl);
    }


    @Override
    public Result<Courier> findById(Long id) {
        Courier courier = courierMapper.selectById(id);
        return Result.success(courier);
    }

    //date : 2013-12
    @Override
    public Result<CourierTradeOrderDetailVO> findCourierMonthTradeOrderInfo(Long courierId, String date) {
        //获取日期中的月份
        Integer month =Integer.parseInt(date.split("-")[1]) ;

        //获取当月的第一天和最后一天
        String firstDayOfMonth = getFirstDayOfMonth(month);
        String lastDayOfMonth = getLastDayOfMonth(month);

        String start = firstDayOfMonth+" 00:00:00";
        String end = lastDayOfMonth+" 23:59:59";

        //  运单平均配送时长  单位-分钟
        Double avgTime = courierTradeOrderMapper.selectOrdersCompleteAvgTime(courierId,start,end);

        //  异常取消的运单量
        Long cancelTotal = courierTradeOrderMapper.selectOrdersCountByCourierIdAndDate(courierId,start,end,CourierTradeOrder.CANCLE_TRADE);

        //  已完成运单单量
        Long completedCount = courierTradeOrderMapper.selectOrdersCountByCourierIdAndDate(courierId,start,end,CourierTradeOrder.TRADE_COMPLETE);

        //  运单配送准时率
        Long onTimeCount = courierTradeOrderMapper.selectOnTimeOrdersByCourierIdAndDate(courierId,start,end);

        Double onTimeRate = onTimeCount/(completedCount*1.0);

        //  运单明细对象
        LocalDate firstDate = LocalDate.parse(firstDayOfMonth);
        LocalDate lastDate = LocalDate.parse(lastDayOfMonth);
        List<String> dateList = new ArrayList<>();
        while (!firstDate.isAfter(lastDate)){
            dateList.add(firstDate.toString());
            firstDate = firstDate.plusDays(1);
        }
        // 查询指定时间段内：每一天的完成订单数
        /**
         *  map格式：
         *      map.key是日期，  map.value是数量
         *  {
         *      "2023-11-23":12,
         *      "2023-11-24":13
         *  }
         */

        Map<String,Long> map1 = courierTradeOrderMapper.selectEveryDayOrdersCountByDateAndStatus(start,end,dateList,CourierTradeOrder.TRADE_COMPLETE);
        // 查询指定时间段内：每一天的取消订单数
        Map<String,Long> map2 = courierTradeOrderMapper.selectEveryDayOrdersCountByDateAndStatus(start,end,dateList,CourierTradeOrder.CANCLE_TRADE);
        List<CourierTradeOrderDetailItemVO> list = new ArrayList<>();
        for(String d:dateList){
            Long everyDayCompleteCount = map1.get(d); //当天完成的订单数
            Long everyDayCancelCount = map2.get(d);  //当天取消的订单数
            CourierTradeOrderDetailItemVO vo = CourierTradeOrderDetailItemVO.builder()
                    .tradeOrderDate(d)
                    .tradeOrdersCompleted(everyDayCompleteCount.intValue())
                    .tradeOrdersCancelled(everyDayCancelCount.intValue())
                    .build();
            list.add(vo);
        }


        //组装
        CourierTradeOrderDetailVO vo =CourierTradeOrderDetailVO.builder()
                .tradeOrderAverageDuration(avgTime)
                .tradeOrdersCancelled(cancelTotal.intValue())
                .tradeOrdersCompleted(completedCount.intValue())
                .tradOrderOnTimeRate(onTimeRate)
                .tradeOrderDetails(list)
                .build();

        return Result.success(vo);
    }

    /**
     * 获取当前月第一天
     * @param month
     * @return
     */
    public String getFirstDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最小天数
        int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
        // 设置日历中月份的最小天数
        calendar.set(Calendar.DAY_OF_MONTH, firstDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String firstDayDate = sdf.format(calendar.getTime());
        return firstDayDate;

    }
    /**
     * 获取当前月最后一天
     * @param month
     * @return
     */
    public String getLastDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最大天数
        int lastDay=0;
        //2月的平年瑞年天数
        if(month==2) {
            lastDay = calendar.getLeastMaximum(Calendar.DAY_OF_MONTH);
        }else {
            lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        // 设置日历中月份的最大天数
        calendar.set(Calendar.DAY_OF_MONTH, lastDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDayDate = sdf.format(calendar.getTime());
        return lastDayDate;

    }

}
